(function(vita, location, window){
    /****
     * end和assist的返回值说明
     *
     * 返回值：数组
     * 第一个元素：目标node的名称，同组件名，类型——字符串或者数组，如果是数组，第一个元素是node名称，第二个元素是入参，类型是对象，
     *          key是入参名，value是入参值（第二个入参可无），第三个元素，类型是布尔值，true时表示需要刷新，当没有上述的入参（第二个元素）时，
     *          该元素将作为第二个元素
     * 第二个元素：回调函数，类型——函数或者数组，如果是数组，第一个元素是函数，第二个元素是上下文对象（可无）
     *
     * 补充：（1）第一个元素，目标node名称后，加":open"，可以使用open或者自定义方式打开，参数为openMethod
     *       (2) 第一个元素，目标node名称后，加":menu"，可以指定容器展示
     *      （3）参数timeout，设定加载超时时间，默认60000毫秒
     * ***/
    vita.widget("webAssist",{
        /**全局缓存**/
        global : {
            prototypes : {},//原型管理
            assists : {},//流程节点管理
            assistElements : {}//流程界面元素管理
        },
        /**组件销毁**/
        _destroy : function(){
            //还原原型，并清除原型缓存
            var prototypes = this.global.prototypes;
            $.each(prototypes, function(key, pt){
                var prototype = eval(key);
                prototype.end = pt.oEnd;
                prototype.assist = pt.oAssist;
                delete prototype.flowing;
            });
            delete this.global.prototypes;
            //清除流程节点缓存
            delete this.global.assists;
            //清除流程界面元素缓存//TODO 是否要销毁所有组件？
            delete this.global.assistElements;
        },
        /**增加流程**/
        add : function(assist){
            this._initPrototype(assist);
            this._initElement(assist);
            this._initAssist(assist);
            return this._getAssistElement(assist.assistName);
        },
        /**初始化原型**/
        _initPrototype : function(assist){
            var widget = this, global = widget.global, prototype = eval(assist.prototype);
            //判断原型是否为对象
            if($.type(prototype) != "object"){
                throw new Error("创建流程失败，指定的prototype(" + assist.prototype + ")不是对象！");
            }
            //判断在指定原型里是否已经创建了流程
            if(!prototype.flowing){
                //保存原型原有的end和assist方法
                global.prototypes[assist.prototype] = {
                    oEnd : prototype.end,
                    oAssist : prototype.assist
                };
                //扩展原型
                $.extend(prototype,{
                    flowing : true,
                    end : function(){
                        var args = [this];
                        widget._end.apply(widget, args.concat(Array.prototype.slice.call(arguments)));
                    },
                    assist : function(){
                        var args = [this];
                        widget._assist.apply(widget, args.concat(Array.prototype.slice.call(arguments)));
                    }
                });
            }
        },
        /**初始化流程节点**/
        _initAssist : function(assist){
            var widget = this, oNodes = assist.nodes, global = widget.global,
                ass = global.assists[assist.assistName] = {
                    prototype : assist.prototype,
                    nodes : {},
                    callBackStack : {},
                    openMethod : assist.openMethod ? assist.openMethod : "open",
                    timeout : assist.timeout ? assist.timeout : 60000,
                    mask : typeof assist.mask === "undefined" ? true : !!assist.mask,
                    plural : !!assist.plural,
                    headers : typeof assist.headers === "undefined" ? null : assist.headers
                }, gNodes = ass.nodes;
            if($.isArray(oNodes) && oNodes.length > 0){
                $.each(oNodes,function(oIndex,node){
                    gNodes[node.name] = node;
                    if(oIndex == 0){
                        ass.firstNode = node;
                    }
                    if(node.name == assist.appointedNode){
                        ass.firstNode = widget.getNode(assist.assistName, assist.appointedNode);
                    }
                });
            }
            //导航到指定节点，否则导航到第一个节点
            var goNode = ass.firstNode;
            goNode.params = assist.params;
            if(goNode.mode == "back-end"){
                widget._forBackEnd(assist.assistName, goNode);
            }else {
                widget.navigate(assist.assistName, goNode.name);
            }
        },
        //从服务获取界面
        _forBackEnd : function (assistName, node) {
            var widget = this, global = this.global, assist = global.assists[assistName];
            vita.ajax(node.url, widget._dealParams($.extend({inFrame : true}, node.params)), function (re) {
                if(re.indexOf("end") == 0){
                    //当前流程结束，操作权交还上级流程
                    var param = re.split("|")[1], e = widget._getAssistElement(assistName);
                    if(!e.parent().is("body")){
                        //如果不是顶级，交还上级
                        if(e && vita.self("isFunction", e.assemble)){
                            e.assemble("end", "end", param);
                        }
                    }else {
                        //如果是顶级，交还本节点
                        var tNode = widget.getNode(assistName, node.name);
                        var nextTar = tNode.end("end", param);
                        widget._toNextTarget(assistName, nextTar, null);
                    }
                }else {
                    var name = $(re).filter("[data-widget]:first").attr("data-widget"), element = widget._getAssistElement(assistName),
                        div = widget._getNodeElement(assistName, name);
                    if(div.length == 0){
                        div = widget._newNodeElement(assistName, name).appendTo(element);
                    }
                    div.html(re);
                    if(!assist.nodes[name]){
                        assist.nodes[name] = {
                            name : name
                        };
                    }
                    widget.navigate(assistName, name);
                }
            }, {mask : assist.mask, timeout : assist.timeout});
        },
        /**初始化流程界面元素**/
        _initElement : function(assist){
            var assistName = assist.assistName, elements = this.global.assistElements[assistName],
                div = $("<div/>").attr({"data-widget":"assemble", "data-assistName":assistName}).css("height", "100%");
            if(!elements){
                elements = this.global.assistElements[assistName] = [];
            }
            if(assist.plural){
                elements.unshift(div);
            }else{
                elements[0] = div;
            }
        },
        /**通过流程名称获取流程元素**/
        _getAssistElement : function (assistName, parent) {
            var re = this.global.assistElements[assistName][0];
            if(parent && parent > 0){
                re = re.parents("div[data-assistName]:eq(" + (parent - 1) + ")");
            }
            return re;
        },
        //切换流程实例
        rotateAssist : function (assistName, vitaId) {
            var re = this.global.assistElements[assistName];
            if(re && re.length > 0){
                var tar = re[0].parent(), newArr = [], tarWidget;
                re[0].detach();
                for(var a in re){
                    tarWidget = re[a].find("[data-vid="+vitaId+"]");
                    if(tarWidget.length == 1){
                        tar.append(re[a]);
                        newArr.unshift(re[a]);
                        if(tarWidget.parent().is("[data-assist]")){
                            tarWidget.parent().show();
                        }else {
                            tarWidget.parentsUntil("[data-assist]").parent().show();
                        }
                    }else {
                        newArr.push(re[a]);
                    }
                }
                this.global.assistElements[assistName] = newArr;
                var nodes = newArr[0].children(), tNode;
                nodes.each(function (index, node) {
                    tNode = $(node);
                    if(tNode.css("display") != "none"){
                        return false;
                    }
                });
                this.navigate(assistName, tNode.attr("data-assist"));
            }
        },
        //释放流程实例
        destroyAssist : function (assistName, vitaId) {
            var re = this.global.assistElements[assistName], container;
            if(re && re.length > 0){
                var newArr = [], cur;
                for(var a in re){
                    if(re[a].find("[data-vid="+vitaId+"]").length == 1){
                        cur = re[a];
                        if(a == 0){
                            //如果删除的是当前的实例，要保留下容器，并在之后自动加载下一个实例，不然后面切换的时候会找不到容器
                            container = cur.parent();
                        }
                    }else {
                        newArr.push(re[a]);
                    }
                }
                container && container.append(newArr[0]);
                this.global.assistElements[assistName] = newArr;
                //释放流程实例
                if(cur){
                    var widgets = cur.find("[data-vid]");
                    widgets.each(function(i, w){
                        var ww = $(w), name = ww.attr("data-widgetfullname").split("-")[1];
                        if($.isFunction(ww[name])){
                            ww[name]("destroy");
                        }
                    });
                    cur.remove();
                }
            }
        },
        /**通过流程名称和节点名称获取节点元素**/
        _getNodeElement : function (assistName, nodeName) {
            return this._getAssistElement(assistName).find("[data-assist="+nodeName+"][data-adhere="+assistName+"]");
        },
        /**创建流程节点**/
        _newNodeElement : function (assistName, nodeName) {
            return $("<div/>").attr({"data-assist":nodeName,"data-adhere":assistName}).css("height", "100%");
        },
        /**获取当前节点所在的流程名称**/
        _getAssistName : function(tarElement){
            return tarElement.closest("[data-assist]").attr("data-adhere");
        },
        /**获取流程设置**/
        _getAssist : function (assistName) {
            return this.global.assists[assistName];
        },
        /**判断是否属于子流程**/
        _isChildrenAssist : function (parent, children) {
            return !!this._getNodeElement(parent, children).children("[data-assistname="+children+"]").length;
        },
        /**end实现**/
        _end : function(){
            var widget = this, tarWidget = arguments[0], nextTar,
                args = Array.prototype.slice.call(arguments,1), assistName = widget._getAssistName(tarWidget.getElement());
            //如果有回调函数，只执行回调函数
            var assist = widget._getAssist(assistName), selfCallBack = assist.callBackStack[tarWidget.getWidgetName()], redirect = args[args.length-1];
            if(selfCallBack && redirect != vita.REDIRECT){
                if(vita.self("isObject",selfCallBack[1])){
                    nextTar = selfCallBack[0].apply(selfCallBack[1], args);
                }else{
                    nextTar = selfCallBack[0].apply(null, args);
                }
                //回调函数执行完，必须删除引用?等下次访问时重置?
                //delete widget.global.callBackStack[tarWidget.getWidgetName()];
                //处理下一个节点
                widget._toNextTarget(assistName, nextTar, tarWidget);
                return;
            }
            //正常处理
            var node = widget.getNode(assistName, tarWidget.getWidgetName());
            if(!!node){
                if($.isFunction(node.end)){
                    nextTar = node.end.apply(tarWidget,args);
                }else{
                    nextTar = widget.global.prototypes[assist.prototype].oEnd.apply(tarWidget,args);
                }
                //处理下一个节点
                widget._toNextTarget(assistName, nextTar, tarWidget);
            }
        },
        _assist : function(){
            var tarWidget = arguments[0], nextTar;
            var widget = this, assistName = widget._getAssistName(tarWidget.getElement()), node = widget.getNode(assistName, tarWidget.getWidgetName()), assist = widget._getAssist(assistName);
            if(!!node){
                var args = Array.prototype.slice.call(arguments,1);
                if($.isFunction(node.assist)){
                    //执行配置数据中的方法
                    nextTar = node.assist.apply(tarWidget,args);
                }else{
                    //没有配置相应方法的时候，执行原来基类的方法
                    nextTar = widget.global.prototypes[assist.prototype].oAssist.apply(tarWidget,args);
                }
                //处理下一个节点
                widget._toNextTarget(assistName, nextTar, tarWidget);
            }
        },
        _toNextTarget : function(assistName, nextTar, tarWidget){
            if(!nextTar){
                return false;
            }
            if(!$.isArray(nextTar)){
                nextTar = [nextTar];
            }
            if(nextTar.length > 0){
                var widget = this, tarName = nextTar[0], callBack = nextTar[1];
                if(!$.isArray(tarName)){
                    tarName = [tarName];
                }
                if(tarName.length > 0){
                    if(!vita.self("isString",tarName[0]) || tarName[0] == ""){
                        throw new Error("指向的目标节点名称错误：名称为（" + tarName[0] + "）");
                    }else{
                        if(tarName[tarName.length - 1] == vita.OUT_OF_FOCUS){
                            //离开当前流程，操作权交还上级流程
                            var e = widget._getAssistElement(assistName);
                            if(e && vita.self("isFunction", e.assemble)){
                                switch (tarName.length){
                                    case 1 : e.assemble("end");break;
                                    case 2 : e.assemble("end", tarName[0]);break;
                                    default : e.assemble("end", tarName[0], tarName[1]);break;
                                }
                            }
                        }else{
                            var node = widget.getNode(assistName, tarName[0]);
                            if(node){
                                //参数处理
                                if(vita.self("isObject",tarName[1])){
                                    //第二个值是对象，判定为参数
                                    node.params = tarName[1];
                                }
                                //最后一个参数判断为是否需要刷新
                                if(tarName[tarName.length - 1] == true){
                                    node.refresh = true;
                                }
                                //如果需要回调，则给目标节点设置回调函数
                                if(!$.isArray(callBack)){
                                    callBack = [callBack];
                                }
                                if(callBack.length > 0){
                                    if($.isFunction(callBack[0])){
                                        widget._getAssist(assistName).callBackStack[tarName[0]] = callBack;
                                    }else{
                                        delete widget.global.assists[assistName].callBackStack[tarName[0]];
                                    }
                                }else{
                                    delete widget.global.assists[assistName].callBackStack[tarName[0]];
                                }
                                //创建目标节点
                                if(node.mode == "back-end"){
                                    widget._forBackEnd(assistName, node);
                                }else if(tarName[0].indexOf(":open") > -1){
                                    node._open = true;
                                    widget.turnOn(assistName, node, function(){
                                        delete node._open;
                                    });
                                }else if(tarName[0].indexOf(":menu") > -1){
                                    widget._doMenu(assistName, tarName, callBack, node, tarWidget);
                                }else{
                                    widget.navigate(assistName, node.name);
                                }
                            }
                        }
                    }
                }
            }
        },
        //导航
        navigate : function(assistName, hash){
            //后面可以在这里选择使用hash还是popstate
            vita.router.navigate(assistName + "/" + hash);
        },
        //获取节点
        getNode : function(assistName, nodeName){
            nodeName = nodeName.split(":")[0];
            var node = this._getAssist(assistName).nodes[nodeName];
            if(!node){
                throw new Error("获取节点失败：名称为（" + nodeName + "）");
            }
            return node;
        },
        //激活节点
        activateNode : function(newHash, oldHash){
            if(!newHash){
                //如果锚点为空，返回
                return false;
            }
            var widget = this, newObj = newHash.split("/"), oldObj = oldHash.split("/"),
                element = widget._getAssistElement(newObj[0]), assist, oldNode;
            var assistConf = this._getAssist(newObj[0]);
            var firstNode = assistConf.firstNode;
            if(element.children().length == 0 && newObj[1] != firstNode.name){
                //如果没有任何节点，且请求的不是第一个节点，则初始化第一个节点
                widget.navigate(newObj[0], firstNode.name);
            }else{
                assist = element.children("[data-assist="+newObj[1]+"]");
                oldNode = oldHash ? widget.getNode(oldObj[0], oldObj[1]) : null;
                //一般节点切换的回调
                var callback = function () {
                    if(oldNode){
                        widget.turnOff(oldObj[0], oldNode);
                    }
                };

                if(oldNode != null && newObj[0] != oldObj[0]){
                    //涉及到流程切换
                    if(widget._isChildrenAssist(oldObj[0], newObj[0])){
                        //新的是旧的的子流程
                        if(vita.router.getPositive() == true){
                            if(oldObj[1] == newObj[0]){
                                //主动切换//只展示新的节点，不能隐藏旧的节点，因为新节点在旧节点里
                                callback = vita.noop;
                            }else {
                                widget.turnOn(oldObj[0], widget.getNode(oldObj[0], newObj[0]), callback);
                                return false;
                            }
                        }else if(vita.router.getPositive() == "back"){
                            //回退键//展示新的节点，隐藏旧节点（父级流程），展示新节点在父级流程里的节点
                            callback = function () {
                                widget.turnOn(oldObj[0], widget.getNode(oldObj[0], newObj[0]), function () {
                                    if(oldNode){
                                        widget.turnOff(oldObj[0], oldNode);
                                    }
                                });
                            };
                        }else if(vita.router.getPositive() == "forward"){
                            //前进键//只展示新的节点，不能隐藏旧的节点，因为新节点在旧节点里
                            widget.turnOn(newObj[0], widget.getNode(newObj[0], newObj[1]));
                            return false;
                        }
                    }else if(widget._isChildrenAssist(newObj[0], oldObj[0])){
                        callback = function () {
                            //widget.turnOff(oldObj[0], oldNode);//貌似可以不用隐藏旧节点，只要隐藏流程即可//TODO
                            if(newObj[1] != oldObj[0]){
                                widget.turnOff(newObj[0], widget.getNode(newObj[0], oldObj[0]));
                            }
                        };
                        //旧的是新的的子流程：展示新的节点，隐藏旧的节点
                        if(vita.router.getPositive() == "back"){
                            //回退键//当前回退到父级流程节点，还要再回退一次
                            widget.turnOn(newObj[0], widget.getNode(newObj[0], newObj[1]), callback);
                            return "back";
                        }
                    }else{
                        //没有直接关系：暂时先这样//TODO
                        //新节点所在流程的节点，如果是隐藏的，需要展示；旧节点所在流程的节点，如果是显示的，需要隐藏
                        //暂不知道能不能通用，或者有其他意外影响
                        var nNode = widget._getAssistElement(newObj[0]), oNode = widget._getAssistElement(oldObj[0]), parentAssistName;
                        if(nNode){
                            nNode = nNode.parent();
                            if(nNode.is("[data-assist="+newObj[0]+"]") && nNode.is(":hidden")){
                                parentAssistName = nNode.attr("data-adhere");
                                widget.turnOn(parentAssistName, widget.getNode(parentAssistName, newObj[0]));
                            }
                        }
                        if(oNode){
                            oNode = oNode.parent();
                            if(oNode.is("[data-assist="+oldObj[0]+"]") && oNode.is(":visible")){
                                parentAssistName = oNode.attr("data-adhere");
                                widget.turnOff(parentAssistName, widget.getNode(parentAssistName, oldObj[0]));
                            }
                        }
                    }
                }else if(oldNode != null && newObj[0] == oldObj[0]){
                    //在同一个流程里
                    var newNode = widget.getNode(newObj[0], newObj[1]);
                    var oN = widget._getNodeElement(oldObj[0], oldObj[1]);
                    if(newNode._container && oN && oN.find(newNode._container).length > 0){
                        callback = $.noop;
                    }
                }
                if(vita.router.getPositive() == "forward"){
                    if(widget._isChildrenAssist(newObj[0], newObj[1])){
                        widget.turnOn(newObj[0], widget.getNode(newObj[0], newObj[1]), callback);
                        return "forward";
                    }
                }

                if(vita.router.getPositive() != true && oldNode && oldNode.onSwitch){
                    var tar = element.children("[data-assist="+oldNode.name+"]").find("[data-widget="+oldNode.name+"]");
                    var wId = tar.attr("data-vid");
                    var w = vita.widget.self("getInstance", oldNode.name, wId);//这个方法，禁止开发人员调用
                    if($.isFunction(oldNode.onSwitch.condition)){
                        //如果不是应用触发，并且设置了切换事件，并且设置了切换条件
                        var doReturn = false;
                        oldNode.onSwitch.condition.call(w, function(result){
                            if(result){
                                //符合执行切换事件的条件
                                if($.isFunction(oldNode.onSwitch.event)){
                                    oldNode.onSwitch.event.call(w);
                                }
                                widget.turnOn(newObj[0], widget.getNode(newObj[0], newObj[1]), function(){
                                    widget.turnOff(oldObj[0], oldNode);
                                });
                            }else{
                                //还原
                                widget.navigate(oldObj[0], oldObj[1]);
                                doReturn = true;
                            }
                        });
                        if(doReturn){
                            return vita.REDIRECT;
                        }
                    }else{
                        //没有设置切换条件，默认执行切换事件
                        widget.turnOn(newObj[0], widget.getNode(newObj[0], newObj[1]), function(){
                            if(oldNode){
                                widget.turnOff(oldObj[0], oldNode, function(){
                                    if($.isFunction(oldNode.onSwitch.event)){
                                        oldNode.onSwitch.event.call(w);
                                    }
                                });
                            }
                        });
                    }
                }else{
                    //忽略切换事件
                    widget.turnOn(newObj[0], widget.getNode(newObj[0], newObj[1]), callback);
                }
            }
        },
        //打开节点
        turnOn : function(assistName, node, callBack){
            var widget = this, element = widget._getAssistElement(assistName), url = node.url,
                callBack = $.isFunction(callBack) ? callBack : $.noop, assistConf = widget._getAssist(assistName);
            //使用open方式打开
            if(node._open == true){
                var open = window[assistConf.openMethod];
                if($.isFunction(open)){
                    open(widget._addParams(node.url, widget._dealParams(node.params)));
                    callBack.call(widget);
                }
                return false;
            }
            //一般处理
            var container = element;
            if(node._container){
                container = node._container;
            }
            var div = container.find("[data-assist="+node.name+"][data-adhere="+assistName+"]");
            if(div.length == 0){
                div = widget._newNodeElement(assistName, node.name).appendTo(container);
            }
            if(div.html() == "" || node.refresh){
                //当容器里没有内容，或者强制刷新时，加载界面
                if(typeof node.params != "object"){
                    node.params = {};
                }else{
                    widget._dealParams(node.params);
                }
                node.params.inFrame = true;
                //销毁节点
                var childIsAssemble = div.children("[data-widget=assemble]"), destroyWidgets = true;
                if(childIsAssemble.length > 0){
                    var childAssistName = childIsAssemble.attr("data-assistname");
                    var childAssist = widget._getAssist(childAssistName);
                    //debugger;
                    if(childAssist.plural){
                        destroyWidgets = false;
                    }
                }
                if(destroyWidgets){
                    var inWidgets = div.find("[data-vid]");
                    inWidgets.each(function(i, w){
                        var ww = $(w), name = ww.attr("data-widgetfullname").split("-")[1];
                        if($.isFunction(ww[name])){
                            ww[name]("destroy");
                        }
                    });
                }else{
                    div.children().detach();
                }
                var options = {
                    mask : assistConf.mask, timeout : assistConf.timeout
                }, headers = typeof node.headers === "undefined" ? assistConf.headers : node.headers;
                switch (vita.type(headers)){
                    case "object" :
                        options.headers = headers;
                        break;
                    case "function" :
                        options.headers = headers();
                        break;
                }
                vita.load(div, url, node.params, function(){
                    delete node.params;
                    delete node.refresh;
                    delete node._container;
                    div.show();
                    callBack.call(widget);
                }, options);
            }else{
                div.show();
                callBack.call(widget);
            }
        },
        //关闭节点
        turnOff : function(assistName, node, callBack){
            this._getNodeElement(assistName, node.name).hide();
            if($.isFunction(callBack)){
                callBack.call(this);
            }
        },
        //处理菜单
        _doMenu : function(assistName, tarName, callBack, node, tarWidget){
            var start = tarName[0].indexOf("(");
            if(start == -1 && $.isFunction(callBack[0])){
                //没送容器id，将url返回
                if(vita.self("isObject", callBack[1])){
                    callBack[0].call(callBack[1], node.url);
                }else{
                    callBack[0](node.url);
                }
            }else{
                //送了id，找容器加载
                var tt;
                var id = tarName[0].substring(start + 1, tarName[0].length - 1);
                if(id.indexOf(".") > 0){
                    var assist = this._getAssistElement(assistName);
                    tt = assist.find("[data-assist="+id.split(".")[0]+"]");
                    id = id.split(".")[1];
                }else {
                    tt = tarWidget.getElement();
                }
                var div = tt.find("#"+id);
                node._container = div;
                this.navigate(assistName, node.name);
            }
        },
        //增加参数
        _addParams : function (url, params) {
            if(params){
                url = url.indexOf("?") > -1 ? url + "&" : url + "?";
                for(var p in params){
                    url += p + "=" + params[p] + "&";
                }
            }
            return url;
        },
        _dealParams : function (obj) {
            for(var key in obj){
                var value = obj[key];
                if(typeof value !== "string"){
                    obj[key] = JSON.stringify(value);
                }
            }
            return obj;
        }
    });

})(window.vita, window.location, window);
(function(vita){
    vita.widget("ui.loading",{
        // get singleton(){
        //     return true;
        // },
        singleton : true,
        options : {
            text : "努力加载中，请稍候"
        },
        _create : function(){
            var loading = $("#body_loading");
            if(loading.length == 0){
                loading = $("<div/>").attr("id", "body_loading").append(
                    $("<div/>").addClass("modal-backdrop fade"),
                    $("<div/>").addClass("fade").append(
                        $("<div/>").addClass("winloding").append(
                            $("<div/>").addClass("imgdiv").append(
                                $("<div/>").addClass("loading"),
                                $("<p/>").addClass("font12")
                            )
                        )
                    )
                ).appendTo("body");
            }
            this.defaultText = this.options.text;
            return loading;
        },
        _init : function(){
            this.element.find("p.font12").html(this.options.text);
        },
        open : function(text){
            if(text){
                this.options.text = text;
            }else{
                this.options.text = this.defaultText;
            }
            this._init();
            this.element.show().children().addClass("in");
        },
        close : function(){
            this.element.hide().children().removeClass("in");
        }
    });
})(window.vita);
(function(vita){
    var date = new Date();
    var datetime,
        mod = document.createElement('modernizr').style,
        defaults = {
            // Options
            width: 70,
            height: 40,
            rows: 3,
            delay: 300,
            disabled: false,
            readonly: false,
            showOnFocus: true,
            showLabel: true,
            wheels: [],
            theme: 'android-ics light',
            headerText: '{value}',
            display: 'modal',//modal 或者 inline
            mode: 'scroller',//scroller 或者 clickpick
            preset: '',
            lang: 'zh',
            setText: '确定',
            cancelText: '取消',
            scrollLock: true,
            tap: true,
            formatResult: function (d) {
                return d.join(' ');
            },
            parseValue: function (value, inst) {
                //不要了
            },
            /////////////
            dateFormat: 'yyyy-mm-dd',
            dateOrder: 'yymmdd',
            timeFormat: 'HH:ii',
            timeWheels: 'HHii',
            startYear: date.getFullYear() - 5,
            endYear: date.getFullYear() + 5,
            monthNames: ['一月', '二月', '三月', '四月', '五月', '六月', '七月', '八月', '九月', '十月', '十一月', '十二月'],
            monthNamesShort: ['1月', '2月', '3月', '4月', '5月', '6月', '7月', '8月', '9月', '10月', '11月', '12月'],
            dayNames: ['周日', '周一;', '周二;', '周三', '周四', '周五', '周六'],
            dayNamesShort: ['日', '一', '二', '三', '四', '五', '六'],
            shortYearCutoff: '+10',
            monthText: '月',
            dayText: '日',
            yearText: '年',
            hourText: '时',
            minuteText: '分',
            secText: '秒',
            ampmText: '&nbsp;',
            nowText: '今天',
            showNow: false,
            stepHour: 1,
            stepMinute: 1,
            stepSecond: 1,
            separator: ' '
        };

    //获取实例
    function getInst(e){
        return scrollers[e.id];
    }

    //判断css属性是否支持
    function testProps(props) {
        var i;
        for (i in props) {
            if (mod[props[i]] !== undefined) {
                return true;
            }
        }
        return false;
    }

    //设置css的浏览器前缀
    function testPrefix() {
        var prefixes = ['Webkit', 'Moz', 'O', 'ms'], p;
        for (p in prefixes) {
            if (testProps([prefixes[p] + 'Transform'])) {
                return '-' + prefixes[p].toLowerCase();
            }
        }
        return '';
    }

    //获取事件坐标
    function getCoord(e, c) {
        var org = e.originalEvent, ct = e.changedTouches;
        return ct || (org && org.changedTouches) ? (org ? org.changedTouches[0]['page' + c] : ct[0]['page' + c]) : e['page' + c];
    }

    //判断是否true或者“true”
    function bool(v) {
        return (v === true || v == "true");
    }

    //所取的值，不能超过指定的最小值和最大值，即取值范围为min <= result <= max
    function constrain(val, min, max) {
        val = val > max ? max : val;
        val = val < min ? min : val;
        return val;
    }

    //不知道做什么的,TODO
    function calc(t, val, dir, anim, orig) {
        val = constrain(val, min, max);
        var cell = $('.dw-li', t).eq(val),
            o = orig === undefined ? val : orig,
            idx = index,
            time = anim ? (val == o ? 0.1 : Math.abs((val - o) * 0.1)) : 0;
        // Set selected scroller value
        inst.temp[idx] = cell.attr('data-val');
        inst.scroll(t, idx, val, time, orig);
        setTimeout(function () {
            // Validate
            inst.validate(idx, dir, time, orig);
        }, 10);
    }

    var scrollers = {},
        timer,
        h,
        min,
        max,
        inst, // Current instance
        uuid = 111111,
        move,
        click,
        target,
        index,
        start,
        stop,
        startTime,
        pos,
        moved,
        scrollable,
        has3d = testProps(['perspectiveProperty', 'WebkitPerspective', 'MozPerspective', 'OPerspective', 'msPerspective']),
        prefix = testPrefix(),
        extend = $.extend,
        tap,
        touch,
        START_EVENT = 'touchstart mousedown',
        MOVE_EVENT = 'touchmove mousemove',
        END_EVENT = 'touchend mouseup',
        onMove = function (e) {
            if (scrollable) {
                e.preventDefault();
                stop = getCoord(e, 'Y');
                inst.scroll(target, index, constrain(pos + (start - stop) / h, min - 1, max + 1));
            }
            moved = true;
        },

        methods = {
            init: function (options) {
                if (typeof options !== "object") {
                    options = {};
                }
                return this.each(function () {
                    if (!this.id) {
                        uuid += 1;
                        this.id = 'scoller' + uuid;
                    }
                    scrollers[this.id] = new Scroller(this, options);
                });
            },
            enable: function () {
                return this.each(function () {
                    var inst = getInst(this);
                    if (inst) {
                        inst.enable();
                    }
                });
            },
            disable: function () {
                return this.each(function () {
                    var inst = getInst(this);
                    if (inst) {
                        inst.disable();
                    }
                });
            },
            isVisible: function () {
                var inst = getInst(this[0]);
                if (inst) {
                    return inst.isVisible();
                }
            },
            option: function (option, value) {
                return this.each(function () {
                    var inst = getInst(this);
                    if (inst) {
                        var obj = {};
                        if (typeof option === 'object') {
                            obj = option;
                        } else {
                            obj[option] = value;
                        }
                        inst.init(obj);
                    }
                });
            },
            setValue: function (d, fill, time, temp) {
                return this.each(function () {
                    var inst = getInst(this);
                    if (inst) {
                        inst.temp = d;
                        inst.setValue(true, fill, time, temp);
                    }
                });
            },
            show: function () {
                var inst = getInst(this[0]);
                if (inst) {
                    return inst.show();
                }
            },
            hide: function () {
                return this.each(function () {
                    var inst = getInst(this);
                    if (inst) {
                        inst.hide();
                    }
                });
            },
            destroy: function () {
                return this.each(function () {
                    var inst = getInst(this);
                    if (inst) {
                        inst.hide();
                        $(this).unbind('.dw');
                        delete scrollers[this.id];
                        if ($(this).is('input')) {
                            this.readOnly = bool($(this).data('dwro'));
                        }
                    }
                });
            }
        };

    function Scroller(elem, settings) {
        var m, hi, v, dw,
            ww, // Window width
            wh, // Window height
            rwh,
            mw, // Modal width
            mh, // Modal height
            anim,
            that = this,
            e = elem,
            elm = $(e),
            s = extend({}, defaults),
            pres = {},
            warr = [],
            iv = {},
            pixels = {},
            input = elm.is('input'),
            visible = false;

        // Private functions

        function isReadOnly(wh) {
            if ($.isArray(s.readonly)) {
                var i = $('.dwwl', dw).index(wh);
                return s.readonly[i];
            }
            return s.readonly;
        }

        function generateWheelItems(i) {
            var html = $("<div/>").addClass("dw-bf"), l = 1, j;
            for (j in warr[i]) {
                html.append(
                    $("<div/>").addClass("dw-li dw-v").attr("data-val",j).css({height:hi+"px","line-height":hi+"px"}).append(
                        $("<div/>").addClass("dw-i").append(warr[i][j])
                    )
                );
                l++;
            }
            return html;
        }

        function setGlobals(t) {
            min = $('.dw-li', t).index($('.dw-v', t).eq(0));
            max = $('.dw-li', t).index($('.dw-v', t).eq(-1));
            index = $('.dw-ul', dw).index(t);
            h = hi;
            inst = that;
        }

        function formatHeader(v) {
            var t = s.headerText;
            return typeof t === 'function' ? t.call(elem, v) : v;
        }

        function read() {
            that.temp = ((input && that.val !== null && that.val != elm.val()) || that.values === null) ? s.parseValue(elm.val() || '', that) : that.values.slice(0);
            that.setValue(true);
        }

        function scrollToPos(time, index, manual, dir, orig) {
            // Call validation event
            if (event('validate', [dw, index, time]) !== false) {
                // Set scrollers to position
                $('.dw-ul', dw).each(function (i) {
                    var t = $(this),
                        cell = $('.dw-li[data-val="' + that.temp[i] + '"]', t),
                        cells = $('.dw-li', t),
                        v = cells.index(cell),
                        l = cells.length,
                        sc = i == index || index === undefined;

                    // Scroll to a valid cell
                    if (!cell.hasClass('dw-v')) {
                        var cell1 = cell,
                            cell2 = cell,
                            dist1 = 0,
                            dist2 = 0;

                        while (v - dist1 >= 0 && !cell1.hasClass('dw-v')) {
                            dist1++;
                            cell1 = cells.eq(v - dist1);
                        }

                        while (v + dist2 < l && !cell2.hasClass('dw-v')) {
                            dist2++;
                            cell2 = cells.eq(v + dist2);
                        }

                        // If we have direction (+/- or mouse wheel), the distance does not count
                        if (((dist2 < dist1 && dist2 && dir !== 2) || !dist1 || (v - dist1 < 0) || dir == 1) && cell2.hasClass('dw-v')) {
                            cell = cell2;
                            v = v + dist2;
                        } else {
                            cell = cell1;
                            v = v - dist1;
                        }
                    }

                    if (!(cell.hasClass('dw-sel')) || sc) {
                        // Set valid value
                        that.temp[i] = cell.attr('data-val');

                        // Add selected class to cell
                        $('.dw-sel', t).removeClass('dw-sel');
                        cell.addClass('dw-sel');

                        // Scroll to position
                        //that.scroll(t, i, v, time);
                        that.scroll(t, i, v, sc ? time : 0.1, sc ? orig : undefined);
                    }
                });

                // Reformat value if validation changed something
                that.change(manual);
            }

        }

        function position(check) {
            var $window = $(window);
            if (s.display == 'inline' || (ww === $window.width() && rwh === $window.height() && check)) {
                return;
            }
            var w, l, t,
                aw, // anchor width
                ah, // anchor height
                ap, // anchor position
                at, // anchor top
                al, // anchor left
                arr, // arrow
                arrw, // arrow width
                arrl, // arrow left
                scroll,
                totalw = 0,
                minw = 0,
                st = $window.scrollTop(),
                wr = $('.dwwr', dw),
                d = $('.dw', dw),
                css = {},
                anchor = s.anchor === undefined ? elm : s.anchor;

            ww = $window.width();
            rwh = $window.height();
            wh = window.innerHeight; // on iOS we need innerHeight
            wh = wh || rwh;

            if (/modal|bubble/.test(s.display)) {
                $('.dwc', dw).each(function () {
                    w = $(this).outerWidth(true);
                    totalw += w;
                    minw = (w > minw) ? w : minw;
                });
                w = totalw > ww ? minw : totalw;
                wr.width(w);
            }

            mw = d.outerWidth();
            mh = d.outerHeight(true);

            if (s.display == 'modal') {
                l = (ww - mw) / 2;
                t = st + (wh - mh) / 2;
            } else if (s.display == 'bubble') {
                scroll = true;
                arr = $('.dw-arrw-i', dw);
                ap = anchor.offset();
                at = ap.top;
                al = ap.left;
                // horizontal positioning
                aw = anchor.outerWidth();
                ah = anchor.outerHeight();
                l = al - (d.outerWidth(true) - aw) / 2;
                l = l > (ww - mw) ? (ww - (mw + 20)) : l;
                l = l >= 0 ? l : 20;
                // vertical positioning
                t = at - mh;
                if ((t < st) || (at > st + wh)) { // if doesn't fit above or the input is out of the screen
                    d.removeClass('dw-bubble-top').addClass('dw-bubble-bottom');
                    t = at + ah;
                } else {
                    d.removeClass('dw-bubble-bottom').addClass('dw-bubble-top');
                }
                // Calculate Arrow position
                arrw = arr.outerWidth();
                arrl = al + aw / 2 - (l + (mw - arrw) / 2);
                // Limit Arrow position to [0, pocw.width] intervall
                $('.dw-arr', dw).css({ left: arrl > arrw ? arrw : arrl });
            } else {
                css.width = '100%';
                if (s.display == 'top') {
                    t = st;
                } else if (s.display == 'bottom') {
                    t = st + wh - mh;
                }
            }

            css.top = t < 0 ? 0 : t;
            css.left = l;
            d.css(css);

            // If top + modal height > doc height, increase doc height
            $('.dw-persp', dw).height(0).height(t + mh > $(document).height() ? t + mh : $(document).height()).css("z-index",9999);

            // Scroll needed
            if (scroll && ((t + mh > st + wh) || (at > st + wh))) {
                $window.scrollTop(t + mh - wh);
            }
        }

        function testTouch(e) {
            if (e.type === 'touchstart') {
                touch = true;
                setTimeout(function () {
                    touch = false; // Reset if mouse event was not fired
                }, 500);
            } else if (touch) {
                touch = false;
                return false;
            }
            return true;
        }

        function event(name, args) {
            var ret;
            args.push(that);
            $.each([pres, settings], function (i, v) {
                if (v[name]) {
                    ret = v[name].apply(e, args);
                }
            });
            return ret;
        }

        function plus(t) {
            var p = +t.data('pos'), val = p + 1;
            calc(t, val > max ? min : val, 1, true);
        }

        function minus(t) {
            var p = +t.data('pos'),
                val = p - 1;
            calc(t, val < min ? max : val, 2, true);
        }

        // Public functions

        /**
         * Enables the scroller and the associated input.
         */
        that.enable = function () {
            s.disabled = false;
            if (input) {
                elm.prop('disabled', false);
            }
        };

        /**
         * Disables the scroller and the associated input.
         */
        that.disable = function () {
            s.disabled = true;
            if (input) {
                elm.prop('disabled', true);
            }
        };

        /**
         * Scrolls target to the specified position
         * @param {Object} t - Target wheel jQuery object.
         * @param {Number} index - Index of the changed wheel.
         * @param {Number} val - Value.
         * @param {Number} time - Duration of the animation, optional.
         * @param {Number} orig - Original value.
         */
        that.scroll = function (t, index, val, time, orig) {

            function getVal(t, b, c, d) {
                return c * Math.sin(t / d * (Math.PI / 2)) + b;
            }

            function ready() {
                clearInterval(iv[index]);
                delete iv[index];
                t.data('pos', val).closest('.dwwl').removeClass('dwa');
            }

            var px = (m - val) * hi, i;

            if (px == pixels[index] && iv[index]) {
                return;
            }

            if (time && px != pixels[index]) {
                // Trigger animation start event
                event('onAnimStart', [dw, index, time]);
            }

            pixels[index] = px;

            t.attr('style', (prefix + '-transition:all ' + (time ? time.toFixed(3) : 0) + 's ease-out;') + (has3d ? (prefix + '-transform:translate3d(0,' + px + 'px,0);') : ('top:' + px + 'px;')));

            if (iv[index]) {
                ready();
            }

            if (time && orig !== undefined) {
                i = 0;
                t.closest('.dwwl').addClass('dwa');
                iv[index] = setInterval(function () {
                    i += 0.1;
                    t.data('pos', Math.round(getVal(i, orig, val - orig, time)));
                    if (i >= time) {
                        ready();
                    }
                }, 100);
            } else {
                t.data('pos', val);
            }
        };

        /**
         * Gets the selected wheel values, formats it, and set the value of the scroller instance.
         * If input parameter is true, populates the associated input element.
         * @param {Boolean} sc - Scroll the wheel in position.
         * @param {Boolean} fill - Also set the value of the associated input element. Default is true.
         * @param {Number} time - Animation time
         * @param {Boolean} temp - If true, then only set the temporary value.(only scroll there but not set the value)
         */
        that.setValue = function (sc, fill, time, temp) {
            if (!$.isArray(that.temp)) {
                that.temp = s.parseValue(that.temp + '', that);
            }

            if (visible && sc) {
                scrollToPos(time);
            }

            v = s.formatResult(that.temp);

            if (!temp) {
                that.values = that.temp.slice(0);
                that.val = v;
            }

            if (fill) {
                if (input) {
                    elm.val(v).trigger('change');
                }
            }
        };

        /**
         * Checks if the current selected values are valid together.
         * In case of date presets it checks the number of days in a month.
         * @param {Number} time - Animation time
         * @param {Number} orig - Original value
         * @param {Number} i - Currently changed wheel index, -1 if initial validation.
         * @param {Number} dir - Scroll direction
         */
        that.validate = function (i, dir, time, orig) {
            scrollToPos(time, i, true, dir, orig);
        };

        /**
         *
         */
        that.change = function (manual) {
            v = s.formatResult(that.temp);
            if (s.display == 'inline') {
                that.setValue(false, manual);
            } else {
                $('.dwv', dw).html(formatHeader(v));
            }

            if (manual) {
                event('onChange', [v]);
            }
        };

        /**
         * Changes the values of a wheel, and scrolls to the correct position
         */
        that.changeWheel = function (idx, time) {
            if (dw) {
                var i = 0, j, k, nr = idx.length;

                for (j in s.wheels) {
                    for (k in s.wheels[j]) {
                        if ($.inArray(i, idx) > -1) {
                            warr[i] = s.wheels[j][k];
                            $('.dw-ul', dw).eq(i).html(generateWheelItems(i));
                            nr--;
                            if (!nr) {
                                position();
                                scrollToPos(time, undefined, true);
                                return;
                            }
                        }
                        i++;
                    }
                }
            }
        };

        /**
         * Return true if the scroller is currently visible.
         */
        that.isVisible = function () {
            return visible;
        };

        /**
         * 触摸或者点击事件
         */
        that.tap = function (el, handler) {
            var startX,
                startY;

            if (s.tap) {
                el.bind('touchstart', function (e) {
                    e.preventDefault();
                    startX = getCoord(e, 'X');
                    startY = getCoord(e, 'Y');
                }).bind('touchend', function (e) {
                    // If movement is less than 20px, fire the click event handler
                    if (Math.abs(getCoord(e, 'X') - startX) < 20 && Math.abs(getCoord(e, 'Y') - startY) < 20) {
                        handler.call(this, e);
                    }
                    tap = true;
                    setTimeout(function () {
                        tap = false;
                    }, 300);
                });
            }

            el.bind('click', function (e) {
                if (!tap) {
                    // If handler was not called on touchend, call it on click;
                    handler.call(this, e);
                }
            });

        };

        /**
         * Shows the scroller instance.
         * @param {Boolean} prevAnim - Prevent animation if true
         */
        that.show = function (prevAnim) {
            if (s.disabled || visible) {
                return false;
            }
            if (s.display == 'top') {
                anim = 'slidedown';
            }
            if (s.display == 'bottom') {
                anim = 'slideup';
            }
            // Parse value from input
            read();
            event('onBeforeShow', [dw]);
            // Create wheels
            var l = 0,
                i,
                label,
                mAnim = '';

            if (anim && !prevAnim) {
                mAnim = 'dw-' + anim + ' dw-in';
            }
            // Create wheels containers
            var dwwr, html =
                $("<div/>").addClass("dw-trans " + s.theme + " dw-" + s.display).append(
                    s.display == "inline" ?
                        $("<div/>").addClass("dw dwbg dwi").append(
                            dwwr = $("<div/>").addClass("dwwr")
                        ) :
                        $("<div/>").addClass("dw-persp").append(
                            $("<div/>").addClass("dwo"),
                            $("<div/>").addClass("dw dwbg " + mAnim).append(
                                $("<div/>").addClass("dw-arrw").append(
                                    $("<div/>").addClass("dw-arrw-i").append(
                                        $("<div/>").addClass("dw-arr")
                                    )
                                ),
                                dwwr = $("<div/>").addClass("dwwr").append(
                                    s.headerText ? $("<div/>").addClass("dwv") : ""
                                )
                            )
                        )
                );

            for (i = 0; i < s.wheels.length; i++) {
                var tr;
                dwwr.append(
                    $("<div/>").addClass("dwc " + (s.mode != "scroller" ? "dwpm" : "dwsc") + " " + (s.showLabel ? "" : "dwhl")).append(
                        $("<div/>").addClass("dwwc dwrc").append(
                            $("<table/>").attr({cellpadding:"0",cellspacing:"0"}).append(
                                tr = $("<tr/>")
                            )
                        )
                    )
                );
                //创建滚轮
                for (label in s.wheels[i]) {
                    warr[l] = s.wheels[i][label];
                    tr.append(
                        $("<td/>").append(
                            $("<div/>").addClass("dwwl dwrc dwwl" + l).append(
                                s.mode != 'scroller' ?
                                    $("<div/>").addClass("dwwb dwwbp").css({height:hi+"px","line-height":hi+"px"}).append(
                                        $("<span/>")
                                    ).add($("<div/>").addClass("dwwb dwwbm").css({height:hi+"px","line-height":hi+"px"}).append(
                                        $("<span/>").html("&ndash;")
                                    )) : "",
                                $("<div/>").addClass("dwl").append(label),
                                $("<div/>").addClass("dww").css({height:(s.rows * hi)+"px","min-width":s.width+"px"}).append(
                                    $("<div/>").addClass("dw-ul").append(generateWheelItems(l)),
                                    $("<div/>").addClass("dwwo")
                                ),
                                $("<div/>").addClass("dwwol")
                            )
                        )
                    );
                    l++;
                }
            }
            dwwr.append(
                s.display != 'inline' ?
                    $("<div/>").addClass("dwbc " + (s.button3 ? "dwbc-p" : "")).append(
                        $("<span/>").addClass("dwbw dwb-s").append(
                            $("<span/>").addClass("dwb").append(s.setText)
                        ),
                        s.button3 ?
                            $("<span/>").addClass("dwbw dwb-n").append(
                                $("<span/>").addClass("dwb").append(s.button3Text)
                            ) : "",
                        $("<span/>").addClass("dwbw dwb-c").append(
                            $("<span/>").addClass("dwb").append(s.cancelText)
                        )
                    ) :
                    $("<div/>").addClass("dwcc")
            );
            dw = html;
            scrollToPos();
            // Show
            if (s.display != 'inline') {
                dw.appendTo('body');
                // Remove animation class
                setTimeout(function () {
                    dw.removeClass('dw-trans').find('.dw').removeClass(mAnim);
                }, 350);
            } else if (elm.is('div')) {
                elm.html(dw);
            } else {
                dw.insertAfter(elm);
            }

            visible = true;

            if (s.display != 'inline') {
                // Init buttons
                that.tap($('.dwb-s span', dw), function () {
                    if (that.hide(false, 'set') !== false) {
                        that.setValue(false, true);
                        event('onSelect', [that.val]);
                    }
                });

                that.tap($('.dwb-c span', dw), function () {
                    that.cancel();
                });

                if (s.button3) {
                    that.tap($('.dwb-n span', dw), s.button3);
                }

                // prevent scrolling if not specified otherwise
                if (s.scrollLock) {
                    dw.bind('touchmove', function (e) {
                        if (mh <= wh && mw <= ww) {
                            e.preventDefault();
                        }
                    });
                }

                // Set position
                position();
                $(window).bind('resize.dw', function () {
                    position(true);
                });
            }

            // Events
            dw.delegate('.dwwl', 'DOMMouseScroll mousewheel', function (e) {
                if (!isReadOnly(this)) {
                    e.preventDefault();
                    e = e.originalEvent;
                    var delta = e.wheelDelta ? (e.wheelDelta / 120) : (e.detail ? (-e.detail / 3) : 0),
                        t = $('.dw-ul', this),
                        p = +t.data('pos'),
                        val = Math.round(p - delta);
                    setGlobals(t);
                    calc(t, val, delta < 0 ? 1 : 2);
                }
            }).delegate('.dwb, .dwwb', START_EVENT, function (e) {
                // Active button
                $(this).addClass('dwb-a');
            }).delegate('.dwwb', START_EVENT, function (e) {
                e.stopPropagation();
                e.preventDefault();
                var w = $(this).closest('.dwwl');
                if (testTouch(e) && !isReadOnly(w) && !w.hasClass('dwa')) {
                    click = true;
                    // + Button
                    var t = w.find('.dw-ul'),
                        func = $(this).hasClass('dwwbp') ? plus : minus;

                    setGlobals(t);
                    clearInterval(timer);
                    timer = setInterval(function () { func(t); }, s.delay);
                    func(t);
                }
            }).delegate('.dwwl', START_EVENT, function (e) {
                // Prevent scroll
                e.preventDefault();
                // Scroll start
                if (testTouch(e) && !move && !isReadOnly(this) && !click) {
                    move = true;
                    $(document).bind(MOVE_EVENT, onMove);
                    target = $('.dw-ul', this);
                    scrollable = s.mode != 'clickpick';
                    pos = +target.data('pos');
                    setGlobals(target);
                    moved = iv[index] !== undefined; // Don't allow tap, if still moving
                    start = getCoord(e, 'Y');
                    startTime = new Date();
                    stop = start;
                    that.scroll(target, index, pos, 0.001);
                    if (scrollable) {
                        target.closest('.dwwl').addClass('dwa');
                    }
                }
            });

            event('onShow', [dw, v]);
        };

        /**
         * Hides the scroller instance.
         */
        that.hide = function (prevAnim, btn) {
            // If onClose handler returns false, prevent hide
            if (!visible || event('onClose', [v, btn]) === false) {
                return false;
            }

            elm.blur();

            // Hide wheels and overlay
            if (dw) {
                if (s.display != 'inline' && anim && !prevAnim) {
                    dw.addClass('dw-trans').find('.dw').addClass('dw-' + anim + ' dw-out');
                    setTimeout(function () {
                        dw.remove();
                        dw = null;
                    }, 350);
                } else {
                    dw.remove();
                    dw = null;
                }
                visible = false;
                pixels = {};
                // Stop positioning on window resize
                $(window).unbind('.dw');
            }
        };

        /**
         * Cancel and hide the scroller instance.
         */
        that.cancel = function () {
            if (that.hide(false, 'cancel') !== false) {
                event('onCancel', [that.val]);
            }
        };

        /**
         * Scroller initialization.
         */
        that.init = function () {
            extend(s, settings);
            that.settings = s;
            // 解绑该目标对象上所有的.dw的事件
            elm.unbind('.dw');
            var preset = datetime.presets[s.preset];
            if (preset) {
                pres = preset.call(elem, that);
                extend(s, pres, settings); // Load preset settings
                extend(methods, pres.methods); // Extend core methods
            }
            // Set private members
            m = Math.floor(s.rows / 2);
            hi = s.height;
            anim = s.animate;

            if (elm.data('dwro') !== undefined) {
                e.readOnly = bool(elm.data('dwro'));
            }
            //默认隐藏
            if (visible) {
                that.hide();
            }
            if (s.display == 'inline') {
                //inline形式默认展现
                that.show();
            } else {
                read();
                if (input && s.showOnFocus) {
                    // Set element readonly, save original state
                    elm.data('dwro', e.readOnly)
                        .prop("readonly", true)
                        .bind('focus.dw', function () { that.show(); });
                }
            }
        };

        that.trigger = function (name, params) {
            return event(name, params);
        };

        that.values = null;
        that.val = null;
        that.temp = null;

        that.init();
    }

    $(document).bind(END_EVENT, function (e) {
        if (move) {
            var time = new Date() - startTime,
                val = constrain(pos + (start - stop) / h, min - 1, max + 1),
                speed,
                dist,
                tindex,
                ttop = target.offset().top;

            if (time < 300) {
                speed = (stop - start) / time;
                dist = (speed * speed) / (2 * 0.0006);
                if (stop - start < 0) {
                    dist = -dist;
                }
            } else {
                dist = stop - start;
            }

            tindex = Math.round(pos - dist / h);

            if (!dist && !moved) { // this is a "tap"
                var idx = Math.floor((stop - ttop) / h),
                    li = $('.dw-li', target).eq(idx),
                    hl = scrollable;

                if (inst.trigger('onValueTap', [li]) !== false) {
                    tindex = idx;
                } else {
                    hl = true;
                }

                if (hl) {
                    li.addClass('dw-hl'); // Highlight
                    setTimeout(function () {
                        li.removeClass('dw-hl');
                    }, 200);
                }
            }

            if (scrollable) {
                calc(target, tindex, 0, true, Math.round(val));
            }

            move = false;
            target = null;

            $(document).unbind(MOVE_EVENT, onMove);
        }

        if (click) {
            clearInterval(timer);
            click = false;
        }

        $('.dwb-a').removeClass('dwb-a');

    }).bind('mouseover mouseup mousedown click', function (e) { // Prevent standard behaviour on body click
        if (tap) {
            e.stopPropagation();
            e.preventDefault();
            return false;
        }
    });

    var preset = function (inst) {
        var that = $(this),
            html5def = {},
            format;
        // Force format for html5 date inputs (experimental)
        if (that.is('input')) {
            switch (that.attr('type')) {
                case 'date':
                    format = 'yy-mm-dd';
                    break;
                case 'datetime':
                    format = 'yy-mm-ddTHH:ii:ssZ';
                    break;
                case 'datetime-local':
                    format = 'yy-mm-ddTHH:ii:ss';
                    break;
                case 'month':
                    format = 'yy-mm';
                    html5def.dateOrder = 'mmyy';
                    break;
                case 'time':
                    format = 'HH:ii:ss';
                    break;
            }
            // Check for min/max attributes
            var min = that.attr('min'),
                max = that.attr('max');
            if (min) {
                html5def.minDate = datetime.parseDate(format, min);
            }
            if (max) {
                html5def.maxDate = datetime.parseDate(format, max);
            }
        }

        // Set year-month-day order
        var s = $.extend({}, defaults, html5def, inst.settings),
            offset = 0,
            wheels = [],
            ord = [],
            o = {},
            i,
            k,
            f = { y: 'getFullYear', m: 'getMonth', d: 'getDate', h: getHour, i: getMinute, s: getSecond, a: getAmPm },
            p = s.preset,
            dord = s.dateOrder,
            tord = s.timeWheels,
            regen = dord.match(/D/),
            ampm = tord.match(/a/i),
            hampm = tord.match(/h/),
            hformat = p == 'datetime' ? s.dateFormat + s.separator + s.timeFormat : p == 'time' ? s.timeFormat : s.dateFormat,
            defd = new Date(),
            stepH = s.stepHour,
            stepM = s.stepMinute,
            stepS = s.stepSecond,
            mind = s.minDate || new Date(s.startYear, 0, 1),
            maxd = s.maxDate || new Date(s.endYear, 11, 31, 23, 59, 59);

        inst.settings = s;

        format = format || hformat;

        if (p.match(/date/i)) {

            // Determine the order of year, month, day wheels
            $.each(['y', 'm', 'd'], function (j, v) {
                i = dord.search(new RegExp(v, 'i'));
                if (i > -1) {
                    ord.push({ o: i, v: v });
                }
            });
            ord.sort(function (a, b) { return a.o > b.o ? 1 : -1; });
            $.each(ord, function (i, v) {
                o[v.v] = i;
            });

            var w = {};
            for (k = 0; k < 3; k++) {
                if (k == o.y) {
                    offset++;
                    w[s.yearText] = {};
                    var start = mind.getFullYear(),
                        end = maxd.getFullYear();
                    for (i = start; i <= end; i++) {
                        w[s.yearText][i] = dord.match(/yy/i) ? i : (i + '').substr(2, 2);
                    }
                } else if (k == o.m) {
                    offset++;
                    w[s.monthText] = {};
                    for (i = 0; i < 12; i++) {
                        var str = dord.replace(/[dy]/gi, '').replace(/mm/, i < 9 ? '0' + (i + 1) : i + 1).replace(/m/, (i + 1));
                        w[s.monthText][i] = str.match(/MM/) ? str.replace(/MM/, '<span class="dw-mon">' + s.monthNames[i] + '</span>') : str.replace(/M/, '<span class="dw-mon">' + s.monthNamesShort[i] + '</span>');
                    }
                } else if (k == o.d) {
                    offset++;
                    w[s.dayText] = {};
                    for (i = 1; i < 32; i++) {
                        w[s.dayText][i] = dord.match(/dd/i) && i < 10 ? '0' + i : i;
                    }
                }
            }
            wheels.push(w);
        }

        if (p.match(/time/i)) {

            // Determine the order of hours, minutes, seconds wheels
            ord = [];
            $.each(['h', 'i', 's', 'a'], function (i, v) {
                i = tord.search(new RegExp(v, 'i'));
                if (i > -1) {
                    ord.push({ o: i, v: v });
                }
            });
            ord.sort(function (a, b) {
                return a.o > b.o ? 1 : -1;
            });
            $.each(ord, function (i, v) {
                o[v.v] = offset + i;
            });

            w = {};
            for (k = offset; k < offset + 4; k++) {
                if (k == o.h) {
                    offset++;
                    w[s.hourText] = {};
                    for (i = 0; i < (hampm ? 12 : 24); i += stepH) {
                        w[s.hourText][i] = hampm && i == 0 ? 12 : tord.match(/hh/i) && i < 10 ? '0' + i : i;
                    }
                } else if (k == o.i) {
                    offset++;
                    w[s.minuteText] = {};
                    for (i = 0; i < 60; i += stepM) {
                        w[s.minuteText][i] = tord.match(/ii/) && i < 10 ? '0' + i : i;
                    }
                } else if (k == o.s) {
                    offset++;
                    w[s.secText] = {};
                    for (i = 0; i < 60; i += stepS) {
                        w[s.secText][i] = tord.match(/ss/) && i < 10 ? '0' + i : i;
                    }
                } else if (k == o.a) {
                    offset++;
                    var upper = tord.match(/A/);
                    w[s.ampmText] = { 0: upper ? 'AM' : 'am', 1: upper ? 'PM' : 'pm' };
                }

            }

            wheels.push(w);
        }

        function get(d, i, def) {
            if (o[i] !== undefined) {
                return +d[o[i]];
            }
            if (def !== undefined) {
                return def;
            }
            return defd[f[i]] ? defd[f[i]]() : f[i](defd);
        }

        function step(v, st) {
            return Math.floor(v / st) * st;
        }

        function getHour(d) {
            var hour = d.getHours();
            hour = hampm && hour >= 12 ? hour - 12 : hour;
            return step(hour, stepH);
        }

        function getMinute(d) {
            return step(d.getMinutes(), stepM);
        }

        function getSecond(d) {
            return step(d.getSeconds(), stepS);
        }

        function getAmPm(d) {
            return ampm && d.getHours() > 11 ? 1 : 0;
        }

        function getDate(d) {
            var hour = get(d, 'h', 0);
            return new Date(get(d, 'y'), get(d, 'm'), get(d, 'd', 1), get(d, 'a') ? hour + 12 : hour, get(d, 'i', 0), get(d, 's', 0));
        }

        inst.setDate = function (d, fill, time, temp) {
            var i;
            // Set wheels
            for (i in o) {
                this.temp[o[i]] = d[f[i]] ? d[f[i]]() : f[i](d);
            }
            this.setValue(true, fill, time, temp);
        };

        inst.getDate = function (d) {
            return getDate(d);
        };

        return {
            button3Text: s.showNow ? s.nowText : undefined,
            button3: s.showNow ? function () { inst.setDate(new Date(), false, 0.3, true); } : undefined,
            wheels: wheels,
            headerText: function (v) {
                return datetime.formatDate(hformat, getDate(inst.temp), s);
            },
            /**
             * Builds a date object from the wheel selections and formats it to the given date/time format
             * @param {Array} d - An array containing the selected wheel values
             * @return {String} - The formatted date string
             */
            formatResult: function (d) {
                return datetime.formatDate(format, getDate(d), s);
            },
            /**
             * Builds a date object from the input value and returns an array to set wheel values
             * @return {Array} - An array containing the wheel values to set
             */
            parseValue: function (val) {
                var d = new Date(), i, result = [];
                try {
                    d = datetime.parseDate(format, val, s);
                } catch (e) {
                }
                for (i in o) {
                    result[o[i]] = d[f[i]] ? d[f[i]]() : f[i](d);
                }
                return result;
            },
            /**
             * Validates the selected date to be in the minDate / maxDate range and sets unselectable values to disabled
             * @param {Object} dw - jQuery object containing the generated html
             * @param {Integer} [i] - Index of the changed wheel, not set for initial validation
             */
            validate: function (dw, i) {
                var temp = inst.temp, //.slice(0),
                    mins = { y: mind.getFullYear(), m: 0, d: 1, h: 0, i: 0, s: 0, a: 0 },
                    maxs = { y: maxd.getFullYear(), m: 11, d: 31, h: step(hampm ? 11 : 23, stepH), i: step(59, stepM), s: step(59, stepS), a: 1 },
                    minprop = true,
                    maxprop = true;
                $.each(['y', 'm', 'd', 'a', 'h', 'i', 's'], function (x, i) {
                    if (o[i] !== undefined) {
                        var min = mins[i],
                            max = maxs[i],
                            maxdays = 31,
                            val = get(temp, i),
                            t = $('.dw-ul', dw).eq(o[i]),
                            y,
                            m;
                        if (i == 'd') {
                            y = get(temp, 'y');
                            m = get(temp, 'm');
                            maxdays = 32 - new Date(y, m, 32).getDate();
                            max = maxdays;
                            if (regen) {
                                $('.dw-li', t).each(function () {
                                    var that = $(this),
                                        d = that.data('val'),
                                        w = new Date(y, m, d).getDay(),
                                        str = dord.replace(/[my]/gi, '').replace(/dd/, d < 10 ? '0' + d : d).replace(/d/, d);
                                    $('.dw-i', that).html(str.match(/DD/) ? str.replace(/DD/, '<span class="dw-day">' + s.dayNames[w] + '</span>') : str.replace(/D/, '<span class="dw-day">' + s.dayNamesShort[w] + '</span>'));
                                });
                            }
                        }
                        if (minprop && mind) {
                            min = mind[f[i]] ? mind[f[i]]() : f[i](mind);
                        }
                        if (maxprop && maxd) {
                            max = maxd[f[i]] ? maxd[f[i]]() : f[i](maxd);
                        }
                        if (i != 'y') {
                            var i1 = $('.dw-li', t).index($('.dw-li[data-val="' + min + '"]', t)),
                                i2 = $('.dw-li', t).index($('.dw-li[data-val="' + max + '"]', t));
                            $('.dw-li', t).removeClass('dw-v').slice(i1, i2 + 1).addClass('dw-v');
                            if (i == 'd') { // Hide days not in month
                                $('.dw-li', t).removeClass('dw-h').slice(maxdays).addClass('dw-h');
                            }
                        }
                        if (val < min) {
                            val = min;
                        }
                        if (val > max) {
                            val = max;
                        }
                        if (minprop) {
                            minprop = val == min;
                        }
                        if (maxprop) {
                            maxprop = val == max;
                        }
                        // Disable some days
                        if (s.invalid && i == 'd') {
                            var idx = [];
                            // Disable exact dates
                            if (s.invalid.dates) {
                                $.each(s.invalid.dates, function (i, v) {
                                    if (v.getFullYear() == y && v.getMonth() == m) {
                                        idx.push(v.getDate() - 1);
                                    }
                                });
                            }
                            // Disable days of week
                            if (s.invalid.daysOfWeek) {
                                var first = new Date(y, m, 1).getDay(),
                                    j;
                                $.each(s.invalid.daysOfWeek, function (i, v) {
                                    for (j = v - first; j < maxdays; j += 7) {
                                        if (j >= 0) {
                                            idx.push(j);
                                        }
                                    }
                                });
                            }
                            // Disable days of month
                            if (s.invalid.daysOfMonth) {
                                $.each(s.invalid.daysOfMonth, function (i, v) {
                                    v = (v + '').split('/');
                                    if (v[1]) {
                                        if (v[0] - 1 == m) {
                                            idx.push(v[1] - 1);
                                        }
                                    } else {
                                        idx.push(v[0] - 1);
                                    }
                                });
                            }
                            $.each(idx, function (i, v) {
                                $('.dw-li', t).eq(v).removeClass('dw-v');
                            });
                        }

                        // Set modified value
                        temp[o[i]] = val;
                    }
                });
            },
            methods: {
                /**
                 * Returns the currently selected date.
                 * @param {Boolean} temp - If true, return the currently shown date on the picker, otherwise the last selected one
                 * @return {Date}
                 */
                getDate: function (temp) {
                    var inst = getInst(this);
                    if (inst) {
                        return inst.getDate(temp ? inst.temp : inst.values);
                    }
                },
                /**
                 * Sets the selected date
                 * @param {Date} d - Date to select.
                 * @param {Boolean} [fill] - Also set the value of the associated input element. Default is true.
                 * @return {Object} - jQuery object to maintain chainability
                 */
                setDate: function (d, fill, time, temp) {
                    if (fill == undefined) {
                        fill = false;
                    }
                    return this.each(function () {
                        var inst = getInst(this);
                        if (inst) {
                            inst.setDate(d, fill, time, temp);
                        }
                    });
                }
            }
        };
    };

    datetime = {
        presets: {
            date : preset,
            time : preset,
            datetime : preset
        },
        //将date按某种格式转换成字符串
        formatDate : function (format, date, settings) {
            if (!date) {
                return null;
            }
            var s = $.extend({}, defaults, settings),
                look = function (m) { // Check whether a format character is doubled
                    var n = 0;
                    while (i + 1 < format.length && format.charAt(i + 1) == m) {
                        n++;i++;
                    }
                    return n;
                },
                f1 = function (m, val, len) { // Format a number, with leading zero if necessary
                    var n = '' + val;
                    if (look(m)) {
                        while (n.length < len) {
                            n = '0' + n;
                        }
                    }
                    return n;
                },
                f2 = function (m, val, s, l) { // Format a name, short or long as requested
                    return (look(m) ? l[val] : s[val]);
                },
                i,
                output = '',
                literal = false;

            for (i = 0; i < format.length; i++) {
                if (literal) {
                    if (format.charAt(i) == "'" && !look("'")) {
                        literal = false;
                    } else {
                        output += format.charAt(i);
                    }
                } else {
                    switch (format.charAt(i)) {
                        case 'd':
                            output += f1('d', date.getDate(), 2);
                            break;
                        case 'D':
                            output += f2('D', date.getDay(), s.dayNamesShort, s.dayNames);
                            break;
                        case 'o':
                            output += f1('o', (date.getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000, 3);
                            break;
                        case 'm':
                            output += f1('m', date.getMonth() + 1, 2);
                            break;
                        case 'M':
                            output += f2('M', date.getMonth(), s.monthNamesShort, s.monthNames);
                            break;
                        case 'y':
                            output += (look('y') ? date.getFullYear() : (date.getYear() % 100 < 10 ? '0' : '') + date.getYear() % 100);
                            break;
                        case 'h':
                            var h = date.getHours();
                            output += f1('h', (h > 12 ? (h - 12) : (h == 0 ? 12 : h)), 2);
                            break;
                        case 'H':
                            output += f1('H', date.getHours(), 2);
                            break;
                        case 'i':
                            output += f1('i', date.getMinutes(), 2);
                            break;
                        case 's':
                            output += f1('s', date.getSeconds(), 2);
                            break;
                        case 'a':
                            output += date.getHours() > 11 ? 'pm' : 'am';
                            break;
                        case 'A':
                            output += date.getHours() > 11 ? 'PM' : 'AM';
                            break;
                        case "'":
                            if (look("'")) {
                                output += "'";
                            } else {
                                literal = true;
                            }
                            break;
                        default:
                            output += format.charAt(i);
                    }
                }
            }
            return output;
        },
        //按某种格式将字符串转成date
        parseDate : function (format, value, settings) {
            var def = new Date();
            if (!format || !value) {
                return def;
            }
            value = (typeof value == 'object' ? value.toString() : value + '');

            var s = $.extend({}, defaults, settings),
                shortYearCutoff = s.shortYearCutoff,
                year = def.getFullYear(),
                month = def.getMonth() + 1,
                day = def.getDate(),
                doy = -1,
                hours = def.getHours(),
                minutes = def.getMinutes(),
                seconds = 0, //def.getSeconds(),
                ampm = -1,
                literal = false, // Check whether a format character is doubled
                lookAhead = function (match) {
                    var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) == match);
                    if (matches) {
                        iFormat++;
                    }
                    return matches;
                },
                getNumber = function (match) { // Extract a number from the string value
                    lookAhead(match);
                    var size = (match == '@' ? 14 : (match == '!' ? 20 : (match == 'y' ? 4 : (match == 'o' ? 3 : 2)))),
                        digits = new RegExp('^\\d{1,' + size + '}'),
                        num = value.substr(iValue).match(digits);

                    if (!num) {
                        return 0;
                    }
                    //throw 'Missing number at position ' + iValue;
                    iValue += num[0].length;
                    return parseInt(num[0], 10);
                },
                getName = function (match, s, l) { // Extract a name from the string value and convert to an index
                    var names = (lookAhead(match) ? l : s), i;
                    for (i = 0; i < names.length; i++) {
                        if (value.substr(iValue, names[i].length).toLowerCase() == names[i].toLowerCase()) {
                            iValue += names[i].length;
                            return i + 1;
                        }
                    }
                    return 0;
                },
                checkLiteral = function () {
                    iValue++;
                },
                iValue = 0,
                iFormat;

            for (iFormat = 0; iFormat < format.length; iFormat++) {
                if (literal) {
                    if (format.charAt(iFormat) == "'" && !lookAhead("'")) {
                        literal = false;
                    } else {
                        checkLiteral();
                    }
                } else {
                    switch (format.charAt(iFormat)) {
                        case 'd':
                            day = getNumber('d');
                            break;
                        case 'D':
                            getName('D', s.dayNamesShort, s.dayNames);
                            break;
                        case 'o':
                            doy = getNumber('o');
                            break;
                        case 'm':
                            month = getNumber('m');
                            break;
                        case 'M':
                            month = getName('M', s.monthNamesShort, s.monthNames);
                            break;
                        case 'y':
                            year = getNumber('y');
                            break;
                        case 'H':
                            hours = getNumber('H');
                            break;
                        case 'h':
                            hours = getNumber('h');
                            break;
                        case 'i':
                            minutes = getNumber('i');
                            break;
                        case 's':
                            seconds = getNumber('s');
                            break;
                        case 'a':
                            ampm = getName('a', ['am', 'pm'], ['am', 'pm']) - 1;
                            break;
                        case 'A':
                            ampm = getName('A', ['am', 'pm'], ['am', 'pm']) - 1;
                            break;
                        case "'":
                            if (lookAhead("'")) {
                                checkLiteral();
                            } else {
                                literal = true;
                            }
                            break;
                        default:
                            checkLiteral();
                    }
                }
            }
            if (year < 100) {
                year += new Date().getFullYear() - new Date().getFullYear() % 100 +
                    (year <= (typeof shortYearCutoff != 'string' ? shortYearCutoff : new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10)) ? 0 : -100);
            }
            if (doy > -1) {
                month = 1;
                day = doy;
                do {
                    var dim = 32 - new Date(year, month - 1, 32).getDate();
                    if (day <= dim) {
                        break;
                    }
                    month++;
                    day -= dim;
                } while (true);
            }
            hours = (ampm == -1) ? hours : ((ampm && hours < 12) ? (hours + 12) : (!ampm && hours == 12 ? 0 : hours));
            var date = new Date(year, month - 1, day, hours, minutes, seconds);
            if (date.getFullYear() != year || date.getMonth() + 1 != month || date.getDate() != day) {
                throw 'Invalid date';
            }
            return date;
        }

    };

    vita.widget("ui.datetime",{
        // get singleton(){
        //     return true;
        // },
        singleton : true,
        _create : function(){

        },
        register : function(tar, options){
            if(!vita.self("isJQueryObj", tar)){
                tar = $(tar);
            }
            methods.init.call(tar, options);
        },
        trigger : function(tar){
            if(!vita.self("isJQueryObj", tar)){
                tar = $(tar);
            }
            tar.focus();
        }
    });
})(window.vita);
(function(vita){
    vita.widget("ui.popup",{
        options : {
            icon : "",
            strong : "",
            text : "",
            buttons : null,
            onClose : null,
            onCancel : null
        },
        _create : function(){
            return $("<div/>").append(
                this._createMask(),
                this._createContent()
            );
        },
        //创建遮罩
        _createMask : function(){
            return $("<div/>").addClass("modal-backdrop fade in");
        },
        //创建图标
        _createIcon : function(){
            var icon = this.options.icon;
            return !!icon ? $("<i/>").addClass("mascotbox").addClass(icon) : null;
        },
        //创建加粗文字
        _createStrong : function(){
            var strong = this.options.strong;
            return !!strong ? $("<br>").add($("<strong/>").addClass("dm font16 padt10").append(strong)) : null;
        },
        //创建文字
        _createText : function(){
            var textCont = $(), text = this.options.text;
            if(!$.isArray(text)){
                text = [text];
            }
            $.each(text, function(i, t){
                textCont = textCont.add($("<p/>").addClass("text-center").append(
                    $("<span/>").append(t)
                ));
            });
            return textCont;
        },
        //创建窗口本体
        _createContent : function(){
            return $("<div/>").addClass("modal fade bs-example-modal-sm in").css("display","block").append(
                $("<div/>").addClass("modal-dialog modal-sm").append(
                    $("<div/>").addClass("modal-content").append(
                        this._createHeader(),
                        this._createBody(),
                        this._createFooter()
                    )
                )
            );
        },
        //创建窗口头部
        _createHeader : function(){
            var widget = this;
            return $("<div/>").addClass("modal-header modal-no").append(
                $("<button/>").attr("type", "button").addClass("pop_radius close").append(
                    $("<span/>").append("×")
                ).click(function(){
                    if($.isFunction(widget.options.onCancel)){
                        widget.options.onCancel.call(widget);
                    }
                    widget.close();
                })
            );
        },
        //创建窗口中部
        _createBody : function(){
            return $("<div/>").addClass("modal-body").append(
                $("<div/>").addClass("text-center").append(
                    this._createIcon(),
                    this._createStrong(),
                    this._createText()
                )
            );
        },
        //创建窗口底部
        _createFooter : function(){
            var footer, group, widget = this, buttons = widget.options.buttons;
            if(buttons){
                if(!$.isArray(buttons)){
                    //如果不是数组，转成数组处理
                    buttons = [buttons];
                }
                if(buttons.length > 0){
                    footer = $("<div/>").addClass("modal-footer nobob").append(
                        group = $("<div/>").addClass("btn-group-justified btn-block60")
                    );
                    $.each(buttons, function(i, button){
                        var customClass = button.class ? button.class : "btnblockho";
                        $("<div/>").addClass("btn-group padlrtb10").append(
                            $("<button/>").attr("type", "button").addClass("btn").addClass(customClass).append(button.text)
                        ).click(function(){
                            if($.isFunction(button.click)){
                                button.click.call(widget);
                            }
                            widget.close();
                        }).appendTo(group);
                    });
                }
            }
            return footer;
        },
        //关闭
        close : function(){
            var widget = this, options = widget.options;
            if($.isFunction(options.onClose)){
                options.onClose.call(widget);
            }
            widget.destroy();
        }
    });
})(window.vita);
(function(vita){
    vita.widget("ui.dialog",{
        options : {
            id : "",
            title : "",
            url : "",
            params : null,
            content : "",
            buttons : null,
            onClose : null,
            onCancel : null,
            destroy : true,
            autoClose : true
        },
        _create : function(){
            return $("<div/>").attr({"data-dialog":"true","id":this.options.id}).append(
                this._createMask(),
                this._createContent()
            );
        },
        //创建遮罩
        _createMask : function(){
            return $("<div/>").addClass("modal-backdrop fade in");
        },
        //创建窗口本体
        _createContent : function(){
            return $("<div/>").addClass("modal fade in popbottom").css({"display":"block","height":"50%"}).append(
                $("<div/>").addClass("modal-dialog popbottom-dialog height100").append(
                    $("<div/>").addClass("modal-content popbottom-content height100").append(
                        this._createHeader(),
                        this._createBody(),
                        this._createFooter()
                    )
                )
            );
        },
        //创建窗口头部
        _createHeader : function(){
            var widget = this, options = widget.options;
            return $("<div/>").addClass("modal-header title-h40").append(
                $("<button/>").attr("type", "button").addClass("close").append(
                    $("<span/>").append("×")
                ).click(function(){
                    if($.isFunction(options.onCancel)){
                        options.onCancel.call(widget, widget.element.find(".modal-body").children());
                    }
                    widget.close();
                }),
                $("<h4/>").addClass("modal-title").append(options.title)
            );
        },
        //创建窗口中部
        _createBody : function(){
            var options = this.options, cDiv = $("<div/>").addClass("modal-body modal-bodyabsolute");
            if(typeof options.url === "string" && options.url != ""){
                vita.load(cDiv, options.url, options.params);
            }else{
                cDiv.append(options.content);
            }
            return cDiv;
        },
        //创建窗口底部
        _createFooter : function(){
            var footer, group, widget = this, buttons = widget.options.buttons, length;
            if(buttons){
                if(!$.isArray(buttons)){
                    //如果不是数组，转成数组处理
                    buttons = [buttons];
                }
                if(buttons.length > 0){
                    length = (100 / buttons.length) + "%";
                    footer = $("<div/>").addClass("modal-footer modal-footerabsolute").append(
                        $("<div/>").addClass("footerblock").append(
                            group = $("<ul/>")
                        )
                    );
                    $.each(buttons, function(i, button){
                        var bg, text;
                        if(button.class == "light"){
                            bg = "botr";
                            text = "text-red";
                        }else{
                            bg = "bgbutt1";
                            text = "text-white";
                        }
                        $("<li/>").addClass(bg).css("width", length).append(
                            $("<a/>").addClass("fontblock").addClass(text).append(button.text)
                        ).click(function(){
                            if($.isFunction(button.click)){
                                button.click.call(widget, widget.element.find(".modal-body").children());
                            }
                            if(widget.options.autoClose){
                                widget.close();
                            }
                        }).appendTo(group);
                    });
                }
            }
            return footer;
        },
        //关闭
        close : function(){
            var widget = this, options = widget.options;
            if($.isFunction(options.onClose)){
                options.onClose.call(widget, widget.element.find(".modal-body").children());
            }
            if(options.destroy){
                widget.destroy();
            }else{
                widget.element.hide();
            }
        },
        //打开
        open : function(){
            this.element.show();
        }
    });
})(window.vita);
(function(vita){
    /**
     * params :
     * 1、obj : 移动过程中显示的html对象
     * 2、start : 移动开始位置
     * 3、end : 移动结束位置
     * 4、processes : 动画过程，可以是对象，也可以是数组，按数组顺序执行
     * {
     *      left :
     *      top :
     *      opacity :
     *      time : 500
     *      callBack : function(){}
     * }
     */
    vita.widget("moveTo", {
        global : {
            time : 500
        },
        _checkParams : function(obj, start, end){
            if(!obj){
                return "没有指定可移动的对象";
            }
            if(!start || !(start.top && start.left)){
                return "没有指定可移动的对象的起始位置";
            }
            if(!end || !(end.top && end.left)){
                return "没有指定可移动的对象的结束位置";
            }
            return true;
        },
        trigger : function(obj, start, end, processes){
            //有动画在执行时，终止
            if($(":animated").length > 0){
                return false;
            }
            //校验参数
            var checkRe = this._checkParams(obj, start, end);
            if(checkRe != true){
                console.error(checkRe);
                return false;
            }
            //转为jquery对象
            if(!vita.self("isJQueryObj", obj)){
                obj = $(obj);
            }
            //执行
            var oPosition = obj.css("position"), oZIndex = obj.css("z-index");
            obj.css({"position":"absolute", "z-index":"9999", "left" : start.left, "top" : start.top});
            var animates = [], global = this.global;
            if(processes){
                if(!vita.self("isArray", processes)){
                    processes = [processes];
                }
                animates = processes;
            }
            animates.push(end);

            var doAnimate = function(){
                if(animates.length > 0){
                    var end = animates.shift(), p = {};
                    if(end.top){
                        p.top = end.top;
                    }
                    if(end.left){
                        p.left = end.left;
                    }
                    if(end.opacity){
                        p.opacity = end.opacity;
                    }
                    obj.animate(p, end.time ? end.time : global.time, function(){
                        if(vita.self("isFunction", end.callBack)){
                            end.callBack();
                        }
                        doAnimate();
                    });
                }else{
                    obj.css({"position":oPosition, "z-index":oZIndex});
                }
            };

            doAnimate();
        }
    });
})(window.vita);
/**
 * @author yangyj
 * @desc htmlTag.js html标签处理
 * @depends core.js
 * @description
 * 1 、 vita-data 用来缓存数据，for属性指定数据缓存的目标，值为id，如果不指定for属性，则将其前一个节点作为缓存目标，如果vita-data是第一个节点，则将父节点作为缓存的目标；标签内的内容为需要缓存的数据，如果是简单字符串，缓存的key为vita-data，如果是json，则按照json的key和value
 * 2 、 vita-bind 数据绑定，for属性同上，action属性指定
 */
(function (vita) {
    vita.widget("htmlTag", {
        init : function (range) {
            //获取检索范围
            range = htmlTag.getRange(range);
            //处理数据附加
            this._data(range);
            //处理数据绑定
            this._bind(range);
        },
        //数据附加
        data : function (range, elementCheckFun) {
            this._data(htmlTag.getRange(range), elementCheckFun);
        },
        _data : function (range, elementCheckFun) {
            var elements = range.find("vita-data,.vita-data");
            elements.each(function (index, element) {
                var tag = $(element), tar = htmlTag.getTarget(tag, range), value = tag.html();
                if(vita.self("isFunction", elementCheckFun)){
                    if(!elementCheckFun(tar)){
                        return true;
                    }
                }
                if(value && typeof value === "string"){
                    value = $.trim(value);
                    if(htmlTag.isJson(value)){
                        //判断为json
                        tar.data(JSON.parse(value));
                    }else{
                        //设置默认key
                        tar.data("vita-data", value);
                    }
                }
                tag.remove();
            });
        },
        //数据绑定
        bind : function (range, modelSetFun, modelBindFun, elementCheckFun) {
            this._bind(htmlTag.getRange(range), modelSetFun, modelBindFun, elementCheckFun);
        },
        _bind : function (range, modelSetFun, modelBindFun, elementCheckFun) {
            range = htmlTag.getRange(range);
            var elements = range.find("vita-bind,.vita-bind");
            elements.each(function (iElement, element) {
                var tag = $(element), tar = htmlTag.getTarget(tag, range),
                    action = tag.attr("action"), mapper = tag.attr("mapper"), model = tag.attr("model"), defaultValue = tag.html();
                if(vita.self("isFunction", elementCheckFun)){
                    if(!elementCheckFun(tar)){
                        return true;
                    }
                }
                if(!model){
                    //没有指定model，返回
                    return true;
                }else{
                    model = model.split(",");
                }
                //没有指定mapper，如果是input，则默认为取value，如果不是input，则默认取html
                mapper = mapper ? mapper.split(",") : htmlTag.isInput(tar) ? ["value"] : ["html"];
                //默认值处理
                if(defaultValue){
                    if(htmlTag.isJson(defaultValue)){
                        defaultValue = JSON.parse(defaultValue);
                    }else{
                        var tObj = {};
                        $.each(mapper, function (iMap, map) {
                            tObj[map] = defaultValue;
                        });
                        defaultValue = tObj;
                    }
                    $.each(mapper, function (iMapper, m) {
                        var value = defaultValue[m] ? defaultValue[m] : null;
                        if(m == "html"){
                            tar.html(value);
                        }else if(m == "value"){
                            tar.val(value);
                        }else {
                            tar.attr(m, value);
                        }
                        vita.self("isFunction", modelSetFun) && modelSetFun(model[iMapper], value);
                    });
                }
                //动作处理
                if(!htmlTag.isInput(tar)){
                    action = null;
                }else {
                    action = action ? action.split(",") : $.support.input ? ["input"] : ["propertychange"];
                }
                var isTrigger = true;
                if(action &&　vita.self("isFunction", modelSetFun)) {
                    //存在指定的model set事件
                    $.each(action, function (iAction, a) {
                        tar.bind(a, function () {
                            isTrigger = false;
                            $.each(mapper, function (i, m) {
                                var value;
                                if(m == "html"){
                                    value = tar.html();
                                }else if(m == "value"){
                                    value = tar.val();
                                }else{
                                    value = tar.attr(m);
                                }
                                modelSetFun(model[i], value);
                            });
                        });
                    });
                }
                if(vita.self("isFunction", modelBindFun)){
                    $.each(mapper, function (i, m) {
                        modelBindFun(model[i], function (value) {
                            var aa = m;
                            if(isTrigger){
                                if(aa == "html"){
                                    tar.html(value);
                                }else if(aa == "value"){
                                    tar.val(value);
                                }else{
                                    tar.attr(m, value);
                                }
                            }
                            isTrigger = true;
                        });
                    });
                }
                tag.remove();
            });
        }
    });

    var htmlTag = {
        //获取检索范围，返回jquery对象
        getRange : function (range) {
            if(!range){
                range = $("body");
            }else if(!vita.self("isJQueryObj", range)){
                range = $(range);
            }
            return range;
        },
        //判断内容是否json
        isJson : function (value) {
            return !!value && value.charAt(0) == "{" && value.charAt(value.length - 1) == "}";
        },
        //获取发生作用的对象
        getTarget : function (tag, source) {
            var tar, tarId = tag.attr("for");
            if(!tarId){
                if(tag.prev().length > 0){
                    tar = tag.prev();
                }else {
                    tar = tag.parent();
                }
            }else{
                tar = source.find("#" + tarId);
            }
            return tar;
        },
        isInput : function (element) {
            if(element.is(":input")){
                return true;
            }else{
                return false;
            }
        }
    };

    //让IE8兼容自定义标签
    if(!$.support.input){
        document.createElement("vita-data");
        document.createElement("vita-bind");
    }
    //隐藏自定义标签
    var head = document.getElementsByTagName("head")[0];
    var style = document.createElement("style"), template = "vita-data,.vita-data,vita-bind,.vita-bind{display:none}";
    if ("styleSheet" in style) {
        style.setAttribute("type", "text/css");
        style.styleSheet.cssText = template;
    }else{
        style.innerHTML = template;
    }
    head.appendChild(style);
})(window.vita);